#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::Dialog)
{
    ui->setupUi(this);
    setFixedSize(width(),height());


    //初始化
    totalBytes = 0;
    bytesWrites = 0;
    bytesToWrites = 0;
    loadSizes = 4 * 1024;//每次发送的大小

    tcp_textSocket = new QTcpSocket(this);
    tcp_fileSocket = new QTcpSocket(this);


    //获取本机ip地址
    QString strLocalIPs = getLocalIPAddress();

    //将返回的IP地址显示到组合框控件里面来
    ui->comboBox_serverAdr->addItem(strLocalIPs);

    ui->pushButton_disconnect->setEnabled(false);
    ui->pushButton_sendFile->setEnabled(false);
    ui->pushButton_sendMsg->setEnabled(false);


    //信号与槽连接
    connect(tcp_textSocket,SIGNAL(disconnected()),this,SLOT(disconnectedFunc()));
    connect(tcp_textSocket,SIGNAL(connected()),this,SLOT(connectedFunc()));
    connect(tcp_textSocket,SIGNAL(readyRead()),this,SLOT(socketReadyReadFunc()));

    //进制消息列表控件，修改里面的数据信息，设置为只读
    ui->plainTextEdit_msgList->setReadOnly(true);

    //当有数据发送成功时，更新进度条状态
    connect(tcp_fileSocket,SIGNAL(bytesWritten(qint64)),
            this,SLOT(updateClientProgressFunc(qint64)));
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.drawPixmap(rect(),QPixmap(":/images/bgpng.png"),QRect());
}

//获取本机ip
QString Dialog::getLocalIPAddress()
{
    QString hostName = QHostInfo::localHostName();
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QList<QHostAddress> addresses = hostInfo.addresses();
    QString hostIP = "";
    if(!addresses.isEmpty())
    {
        for(int i=0;i<addresses.size();i++)
        {
            QHostAddress address = addresses.at(i);
            if(address.protocol() == QAbstractSocket::IPv4Protocol)
            {
                hostIP = address.toString();
                break;
            }
        }
    }
    ui->label_localAdr->setText(ui->label_localAdr->text() + hostIP);
    return hostIP;

}
//关闭窗口事件
void Dialog::closeEvent(QCloseEvent *event)
{
    if(tcp_textSocket->state() == QAbstractSocket::ConnectedState)
    {
        tcp_textSocket->close();
    }
    if(tcp_fileSocket->state() == QAbstractSocket::ConnectedState)
    {
        tcp_fileSocket->close();
    }

    event->accept();
}


void Dialog::on_pushButton_connect_clicked()
{
    QString hostIP = ui->comboBox_serverAdr->currentText();
    int port = ui->spinBox_serverPort->value();
    tcp_textSocket->connectToHost(QHostAddress(hostIP),port);
    ui->pushButton_connect->setEnabled(false);
    ui->pushButton_disconnect->setEnabled(true);

    bytesWrites = 0;
    tcp_fileSocket->connectToHost(QHostAddress(hostIP),port);

}

void Dialog::on_pushButton_disconnect_clicked()
{
    ui->pushButton_connect->setEnabled(true);
    ui->pushButton_disconnect->setEnabled(false);
    tcp_textSocket->close();
}

//退出系统
void Dialog::on_pushButton_exit_clicked()
{
    tcp_textSocket->close();
    tcp_fileSocket->close();
    this->close();
}
//清空文本
void Dialog::on_pushButton_clear_clicked()
{
    ui->plainTextEdit_msgList->clear();
}

void Dialog::on_pushButton_sendMsg_clicked()
{
    QString strTemp = ui->plainTextEdit_sendMsg->toPlainText();

    if(strTemp.isEmpty())
    {
        QMessageBox::information(this,"错误","发送到服务器的数据不能为空，请重新检查",QMessageBox::Ok);
        ui->plainTextEdit_sendMsg->setFocus();
        return;
    }

    strTemp.append("\n");
    QByteArray array =strTemp.toLatin1();
    tcp_textSocket->write(array);


    QDateTime dateTime = QDateTime::currentDateTime();
    QString strDateTime = dateTime.toString("yyyy-MM-dd hh:mm:ss");
    ui->plainTextEdit_msgList->appendPlainText("[" + strDateTime + " 客户端发送]:" + strTemp);
    ui->plainTextEdit_sendMsg->clear();
}

//选择文件
void Dialog::on_pushButton_chooseFile_clicked()
{
    fileNames = QFileDialog::getOpenFileName(this,"请选择要传输的文件");
    if(!fileNames.isEmpty())
    {
        ui->plainTextEdit_msgList->appendPlainText(QString("[客户端打开文件为]:%1 成功").arg(fileNames));
        //启用发送文件按钮
        ui->pushButton_sendFile->setEnabled(true);

    }

}


//发送文件
void Dialog::on_pushButton_sendFile_clicked()
{
    //1.根据文件名新建文件并打开
    localFile = new QFile(fileNames);
    if(!localFile->open(QFile::ReadOnly))
    {
        QMessageBox::critical(this,"错误","打开文件错误,请重新检查",QMessageBox::Ok);
        return;
    }

    //2.得到本身文件的大小，不包含头部信息
    totalBytes=localFile->size();

    //3.处理文件名，提取出不含路径的文件名
    QString strCurrentFileName = fileNames.right(fileNames.size() - fileNames.lastIndexOf('/') - 1);


    //4.将 QDataStream 关联到 QByteArray 时，实际上是将序列化后的数据写入到这个头部信息字节数组中
    QDataStream sendDataOut(&buff,QIODevice::WriteOnly);


    //5.依次进行写入文件的总大小信息空间、文件名总大小信息空间、文件名
    sendDataOut << qint64(0) << qint64(0) << strCurrentFileName;

    //6.总大小是文件名大小等信息和实际文件大小的总和
    totalBytes = totalBytes + buff.size();


    //将数据流指针移动到头部（回到开头）
    sendDataOut.device()->seek(0);

    //返回sendDataOut的开始，用实际的大小信息代替两个qint64(0)空间
    // -> [totalBytes总大小][文件名长度][strCurrentFileName]
    sendDataOut << totalBytes << qint64((buff.size() - sizeof(qint64)*2));

    //发送完前面数据之后，剩下数据的大小
    bytesToWrites = totalBytes - tcp_fileSocket->write(buff);

    //重置
    buff.resize(0);


}

void Dialog::connectedFunc()
{
    ui->pushButton_sendMsg->setEnabled(true);
    ui->plainTextEdit_msgList->appendPlainText("[客户端已经连接上服务器...]");
}

void Dialog::disconnectedFunc()
{
    ui->pushButton_sendMsg->setEnabled(false);
    if(tcp_textSocket->state() == QAbstractSocket::ConnectedState)
    {
        //优雅地关闭连接，套接字的状态会变为 QAbstractSocket::ClosingState。等到所有待处理的数据都传输完毕，
        //并且接收到对方的 FIN 包后，状态才会变为 QAbstractSocket::UnconnectedState。
        tcp_textSocket->disconnectFromHost();
    }
    ui->plainTextEdit_msgList->appendPlainText("[客户端已经和服务器断开连接...]");
}

void Dialog::socketReadyReadFunc()
{
    qDebug() << "123";
    QDateTime dateTime = QDateTime::currentDateTime();
    QString strDateTime = dateTime.toString("yyyy-MM-dd hh:mm:ss");
    QString strTemp = "";
    while(tcp_textSocket->canReadLine())
    {
       QByteArray temp = tcp_textSocket->readLine();
       strTemp += temp;
    }
    ui->plainTextEdit_msgList->appendPlainText("[" +strDateTime + " 收到服务端]:" + strTemp);
}

//传输文件信息
void Dialog::startTransferFunc()
{

}

//实现文件传输过程中，进度条变化状态显示
void Dialog::updateClientProgressFunc(qint64 numBytes)
{
    qDebug() << "123456";
    //确认已发送数据信息的大小
    bytesWrites = bytesWrites + (int)numBytes;
    if(bytesToWrites > 0)//剩下数据大小
    {
        //从文件当中去除数据到发送缓冲区，但是每次发送文件大小数据，设置为4kb
        //如果剩下的数据不满足4KB，就发送剩下数据大小
        buff = localFile->read(qMin(bytesToWrites,loadSizes));

        //从发送缓冲区发送数据，计算发送完一次数据后还剩下的数据大小
        bytesToWrites = bytesToWrites - (int)tcp_fileSocket->write(buff);

        //清空发送缓冲区数据信息
        buff.resize(0);
    }
    else
    {
        localFile->close();//没有数据发送了,则直接关闭文件
    }

    //进度条更新
    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(bytesWrites);

    //发送的数据大小 等于 数据总大小 ， 说明发送完毕
    if(bytesWrites == totalBytes)
    {
        ui->plainTextEdit_msgList->appendPlainText(QString("[文件已经成功传输到服务器]: %1 成功").
                                                   arg(fileNames));
        localFile->close();

    }
}

void Dialog::displayErrorFunc(QAbstractSocket::SocketError)
{

}
